############################################################
# 神经网络
############################################################
import numpy as np


def step_func(x):
    # 阶跃函数
    return 1 if x > 0 else 0


def sigmoid(x):
    # sigmoid函数
    return 1/(1+np.exp(-x))


def ReLU(x):
    # ReLU函数
    return x if x > 0 else 0


def x2y(w, x, b, g='Linear'):
    # 输出y=g(w*x+b)
    z = np.dot(w, x)+b
    if g == 'Linear':
        return z
    elif g == 'Log':
        return np.exp(z)
    elif g == 'Exp':
        return np.log(z)
    else:
        print('未预设联系函数，请检查g参数')
        raise


def initW(in_num, out_num, way='normal'):
    """
    # 初始化W权重矩阵
    # way为元组(a，b，随机分布方式)
    """
    if way[2] == 'uniform':
        # 均匀分布，范围为[a,b)
        return np.random.uniform(way[0], way[1], (in_num, out_num))
    elif way[2] == 'normal':
        # 正态分布，均值为a，标准差为b
        return np.random.normal(way[0], way[1], (in_num, out_num))
    elif way[2] == 'poisson':
        # 泊松分布，均值为a
        return np.random.poisson(way[0], (in_num, out_num))
    elif way[2] == 'exp':
        # 指数分布，均值为a
        return np.random.exponential(way[0], (in_num, out_num))
    else:
        print('未预设分布，请检查way参数')
        raise


def initB(out_num, way='normal'):
    """
    # 初始化B权重矩阵
    # way为元组(a，b，随机分布方式)
    """
    if way[2] == 'uniform':
        # 均匀分布，范围为[a,b)
        return np.random.uniform(way[0], way[1], (1, out_num))
    elif way[2] == 'normal':
        # 正态分布，均值为a，标准差为b
        return np.random.normal(way[0], way[1], (1, out_num))
    elif way[2] == 'poisson':
        # 泊松分布，均值为a
        return np.random.poisson(way[0], (1, out_num))
    elif way[2] == 'exp':
        # 指数分布，均值为a
        return np.random.exponential(way[0], (1, out_num))
    else:
        print('未预设分布，请检查way参数')
        raise


def getLoss(x, y, loss='MSE'):
    if loss == 'MSE':
        return np.var(y-x)
    elif loss == 'Mean':
        return np.mean(y-x)
    else:
        print('未预设误差计算方法，请检查loss参数')
        raise


class Neuron:
    def __init__(self, in_num, out_num, way='normal'):
        self.nin = in_num
        self.nout = out_num
        self.way = way
        self.W = initW(self.nin, self.nout, self.way)
        self.B = initB(self.nout, self.way)
